package com.tyl.xtk.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import com.tyl.xtk.beans.po.FileInfo;
import com.tyl.xtk.beans.vo.Result;
import com.tyl.xtk.service.FileInfoService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.time.LocalDateTime;

/**
 * 文件管理控制器
 */
@RestController
@RequestMapping("file")
@Tag(name = "文件管理")
public class FileController {

    @Resource
    private FileInfoService fileInfoService;

    @Value("${spring.file.storage-path}")
    private String storagePath;

    /**
     * @param file 文件
     * @return 文件信息
     */
    @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @Operation(summary = "上传文件")
    @SaCheckPermission("file:post")
    @Transactional
    public Result<FileInfo> upload(@RequestPart("file") MultipartFile file) {
        try {
            // 创建文件信息记录
            FileInfo fileInfo = new FileInfo();
            fileInfo.setName(file.getOriginalFilename());
            fileInfo.setContentType(file.getContentType());
            fileInfo.setCreateTime(LocalDateTime.now());

            // 保存文件信息到数据库
            fileInfoService.insert(fileInfo);

            // 保存文件到文件系统
            String filePath = storagePath + File.separator + fileInfo.getId();
            Path path = Paths.get(filePath);
            Files.createDirectories(path.getParent());
            Files.copy(file.getInputStream(), path, StandardCopyOption.REPLACE_EXISTING);

            // 更新文件路径信息
            fileInfo.setFilePath(filePath);
            fileInfoService.update(fileInfo);

            return Result.success(fileInfo);
        } catch (IOException e) {
            return Result.fail("文件上传失败: " + e.getMessage());
        }
    }

    /**
     * 流式下载文件
     *
     * @param id       文件ID
     * @param response HTTP响应
     */
    @GetMapping("/download/{id}")
    @Operation(summary = "获取文件")
    @SaCheckPermission("file:one")
    public void download(@PathVariable Long id, HttpServletResponse response) {
        try {
            // 获取文件信息
            FileInfo fileInfo = fileInfoService.selectById(id);
            if (fileInfo == null) {
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                return;
            }

            // 如果文件被标记为删除恢复文件(updateTime 会自动填入)
            if (fileInfo.getDeleted()) {
                fileInfo.setDeleted(false);
                fileInfoService.update(fileInfo);
            }

            // 设置响应头
            response.setContentType(fileInfo.getContentType());
            String encodedFileName = URLEncoder.encode(fileInfo.getName(), StandardCharsets.UTF_8);
            response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedFileName + "\"");

            // 读取文件并写入响应
            Path path = Paths.get(fileInfo.getFilePath());
            Files.copy(path, response.getOutputStream());
        } catch (IOException e) {
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        }
    }


}